﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Collections.Specialized;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.IO;
using System.Threading;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;
using OntologyUtility.Interfaces;



namespace OntologyUtility.Xml
{
    public class XmlWriter
    {
        XmlDocument form;
        public string name { get; set; }
        

        public XmlWriter()
        {
            name = XmlData.XMLNAME;
            form = new XmlDocument();
            
            XmlElement xmlRootForm = form.CreateElement("", XmlData.XMLNAME, "");
            form.AppendChild(xmlRootForm);
        }

        public void removeAll() {
            XmlNode root = form.SelectSingleNode(name);
            root.RemoveAll();
        }

        public void addForm(IWidgetContainer _form)
        {
            try
            {
                XmlNode root = form.SelectSingleNode(name);

                WriteForm(_form, _form.GetType(), ref root);
               
            }
            catch (Exception e)
            {
                Console.WriteLine("addForm: " + e.ToString());
            }
        }
        
        public void SaveXml(string path)
        {
            try
            {
                form.Save(path);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }


        private void getChild(XmlNode node) {
            XmlNodeList list = node.ChildNodes;

            for (int i = 0; i < list.Count; i++)
            {
                XmlNode _node = list[i];
            }

        }


        //add by v
        private void addChild(String value, String element, ref XmlNode node)
        {
            XmlNode _node = form.CreateNode(XmlNodeType.Element, element, null);
            XmlAttribute _attr = form.CreateAttribute("Value");
            _attr.Value = value;
            _node.Attributes.Append(_attr);
            //node.InnerText = value;
            node.AppendChild(_node);
        }


        //add by v
        private void addProperty(String value, String property, ref XmlNode node)
        {
            XmlAttribute _attr = form.CreateAttribute(property);
            _attr.Value = value;
            node.Attributes.Append(_attr);
        }

        //add by v
        private void WriteForm(Object widget, Type type, ref XmlNode root)
        {
            XmlNode xmlNode = form.CreateNode(XmlNodeType.Element, type.Name, null);
                        
            PropertyInfo[] propertyInfoThis = type.GetProperties();
            List<PropertyInfo> propertyInfo = new List<PropertyInfo>();
            propertyInfo.AddRange(propertyInfoThis);
            //propertyInfo.Concat();
            foreach (Type t1 in type.GetInterfaces())
                if (!(t1 is IList))
                    propertyInfo.AddRange(t1.GetProperties());
            
            for (int i = 0; i < propertyInfo.Count; i++)
            {
                object[] attributes = propertyInfo[i].GetCustomAttributes(true);
                for (int j = 0; j < attributes.Length; j++)
                {
                    if (attributes[j] is XmlNodeTypeAttribute)
                    if (((XmlNodeTypeAttribute)attributes[j]).Type.Equals(XmlNodeType.Element))
                    {   
                        try
                        {
                            Console.WriteLine("Property: " + propertyInfo[i].ToString());
                            if (typeof(IList).IsAssignableFrom(propertyInfo[i].ReflectedType.GetProperty(propertyInfo[i].Name).PropertyType))
                            {
                                Console.WriteLine("IList");// è una list quindi la devo scorrere...
                                //creo l'elemento contenitore
                                XmlNode xmlList = form.CreateNode(XmlNodeType.Element, propertyInfo[i].Name, null);
                                foreach (object obj in (widget.GetType().InvokeMember(propertyInfo[i].Name, BindingFlags.GetProperty, null, widget, new Object[0]) as IList))
                                    WriteForm(
                                        obj,
                                        obj.GetType(),
                                        ref xmlList
                                    );
                                xmlNode.AppendChild(xmlList);
                            }
                            else 
                                WriteForm(
                                    widget.GetType().InvokeMember(propertyInfo[i].Name, BindingFlags.GetProperty, null, widget, new Object[0]),
                                    propertyInfo[i].ReflectedType.GetProperty(propertyInfo[i].Name).PropertyType, 
                                    ref xmlNode
                                );
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("Element ex: " + e.ToString());
                        }
                    }
                    else if (((XmlNodeTypeAttribute)attributes[j]).Type.Equals(XmlNodeType.Attribute))
                    {
                        try
                        {
                            
                            String value = widget.GetType().InvokeMember(propertyInfo[i].Name, BindingFlags.GetProperty, null, widget, new Object[0]).ToString();
                            String property = propertyInfo[i].Name;
                            Console.WriteLine("Attribute: " + property + " value " + value);
                            addProperty(value, property, ref xmlNode);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("Attribute ex: " + e.ToString());
                        }
                    }
                }
            }
            root.AppendChild(xmlNode);
        }
    }
}
